package com.yami.shop.delivery.common.service.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.enums.DvyType;
import com.yami.shop.bean.model.Sku;
import com.yami.shop.bean.model.UserAddr;
import com.yami.shop.common.util.Arith;
import com.yami.shop.common.util.BmapPoint;
import com.yami.shop.common.util.GraphUtils;
import com.yami.shop.delivery.common.dao.SameCityMapper;
import com.yami.shop.delivery.common.model.SameCity;
import com.yami.shop.delivery.common.service.SameCityService;
import com.yami.shop.service.ShopDetailService;
import com.yami.shop.service.SkuService;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author lhd
 * @date 2020-05-23 08:26:25
 */
@Service
@AllArgsConstructor
public class SameCityServiceImpl extends ServiceImpl<SameCityMapper, SameCity> implements SameCityService {

    private final ShopDetailService shopDetailService;
    private final SkuService skuService;

    @Override
    public Double calculateTransFee(List<ShopCartItemDto> shopCartItems, UserAddr userAddr) {
        double transFee = 0.0;
        if(CollectionUtils.isEmpty(shopCartItems) || Objects.isNull(userAddr)){
            return transFee;
        }
        Long shopId = shopCartItems.get(0).getShopId();
        SameCity sameCity = getSameCityByShopId(shopId);
        // 如果商家没有配好同城配送或者没有启用的模板，直接返回 -2
        if(Objects.isNull(sameCity) || Objects.equals(sameCity.getStatus(),0)){
            return -2.0;
        }
        //计算当前的坐标点
        BmapPoint bmapPoint = new BmapPoint(userAddr.getLng(),userAddr.getLat());
        JSONArray jsonArray = JSONUtil.parseArray(sameCity.getPositionIds());
        sameCity.setPolygonPath(jsonArray.toList(BmapPoint.class));
        boolean point = GraphUtils.isPointInPolygon(bmapPoint, sameCity.getPolygonPath());
        //如果不在配送范围，直接返回 -1
        if(!point){
            return -1.0;
        }
        List<Long> skuIds = new ArrayList<>();
        shopCartItems.forEach(shopCartItemDto -> skuIds.add(shopCartItemDto.getSkuId()));
        Collection<Sku> skuList = skuService.listByIds(skuIds);
        // 计算总重、总价
        double productTotalAmount = 0.0;
        double productTotalWeight = 0.0;
        if(CollectionUtils.isNotEmpty(skuList)){
            Map<Long, Double> skuWeightMap = skuList.stream().collect(Collectors.toMap(Sku::getSkuId, Sku::getWeight));
            for (ShopCartItemDto shopCartItem : shopCartItems) {
                Double skuWeight = skuWeightMap.get(shopCartItem.getSkuId());
                double skuTotalWeight = Arith.mul(skuWeight,shopCartItem.getProdCount());
                productTotalAmount = Arith.add(productTotalAmount,shopCartItem.getProductTotalAmount());
                productTotalWeight = Arith.add(productTotalWeight,skuTotalWeight);
            }
        }
        //1.先判断起送费有没有够,没够直接返回 -3
        if(sameCity.getStartingFee() > productTotalAmount){
            return -3.0;
        }

        //2.判断收费类型 2.1 固定费用先加上
        transFee = sameCity.getDeliveryFee();
        if (sameCity.getChargeType().equals(DvyType.STATION.value())) {
            // 2.2按距离收费,sql查询出来的单位是m
            double distance = shopDetailService.getDistance(userAddr.getLat(), userAddr.getLng(),shopId);
            distance = Arith.div(distance,1000,1);
            if(distance > sameCity.getHeadDistance()){
                // 减去免费配送距离
                double prodContinuousPiece = Arith.sub(distance,sameCity.getHeadDistance());
                // 超出距离的倍数，向上取整
                int mulNumber = (int) Math.ceil(Arith.div(prodContinuousPiece, sameCity.getOverDistance()));
                // 超出距离的运费
                double continuousFee = Arith.mul(mulNumber, sameCity.getOverDistanceFee());
                transFee = Arith.add(continuousFee, transFee);
            }
        }
        //3.按重量计算运费
        double piece = productTotalWeight;
        if (piece > sameCity.getFreeWeight() && Objects.nonNull(sameCity.getOverWeight()) && sameCity.getOverWeight() > 0.0) {
            // 续重重量
            double prodContinuousPiece = Arith.sub(piece,sameCity.getFreeWeight());
            // 续重重量的倍数，向上取整
            double mulNumber = (int) Math.ceil(Arith.div(prodContinuousPiece, sameCity.getOverWeight()));
            // 续重数量运费
            double continuousFee = Arith.mul(mulNumber, sameCity.getOverWeightFee());
            transFee = Arith.add(continuousFee, transFee);
        }
        return transFee;
    }

    @Override
    @Cacheable(cacheNames = "SameCityInfo", key = "#shopId")
    public SameCity getSameCityByShopId(Long shopId) {
        return getOne(new LambdaQueryWrapper<SameCity>().eq(SameCity::getShopId,shopId));
    }

    @Override
    @CacheEvict(cacheNames = "SameCityInfo", key = "#shopId")
    public void removeSameCityByShopId(Long shopId) {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSameCity(SameCity sameCity) {
        SameCity sameCityDb = getOne(new LambdaQueryWrapper<SameCity>().eq(SameCity::getShopId, sameCity.getShopId()));
        JSONArray jsonArray = new JSONArray(sameCity.getPolygonPath());
        sameCity.setPositionIds(jsonArray.toString());
        if (Objects.nonNull(sameCityDb)) {
            updateById(sameCity);
        } else {
            save(sameCity);
        }
    }

    @Override
    @CacheEvict(cacheNames = "SameCityInfo", key = "#shopId")
    public void removeCache(Long shopId) {}
}

